package qqserver.service;

import javafx.print.Printer;
import qqcommon.Message;
import qqcommon.MessageType;
import qqcommon.User;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 这是服务器，监听9999端口，等待客户端的连接并并保持通信
 */
public class QQServer {
    private ServerSocket ss = null;
    //创建一个集合用来模拟数据库存放多个用户
    //HashMap 没有处理多线程，即多线程下是不安全的
    //也可使用 ConcurrentHashMap,可以处理并发的集合，线程同步处理，多线程下是安全的
    private static ConcurrentHashMap<String,User> validUsers = new ConcurrentHashMap<>();

    // 添加新用户
    public static void addUser(User user) {
        validUsers.put(user.getUserId(), user);
    }

    //判断用户是否存在
    public static boolean isUserExists(String userId) {
        return validUsers.containsKey(userId);
    }
    public static ConcurrentHashMap<String, User> getValidUsers() {
        return validUsers;
    }

    static {//在静态代码块中，初始化 validUsers
        validUsers.put("100",new User("100","123456"));
        validUsers.put("200",new User("200","123456"));
        validUsers.put("300",new User("300","123456"));
        validUsers.put("至尊宝",new User("至尊宝","123456"));
        validUsers.put("紫霞仙子",new User("紫霞仙子","123456"));

    }
    //验证用户是否有效的方法
    private boolean checkUser(String userId, String userPwd){
        User user = validUsers.get(userId);
        if (user == null){//说明userId没有存在 validUsers 的key中，即账号不存在
            return false;
        }
        if (!user.getUserPwd().equals(userPwd)){//userId正确，密码错误
            return false;
        }
        return true;
    }

    public QQServer() {
        try {
            System.out.println("服务端正在监听9999端口中。。。");
            // 启动推送消息的线程
            new Thread(new SendNewsToAllService()).start();
            ss = new ServerSocket(9999);

            while (true) { // 当和某个客户端连接后，会继续监听
                Socket socket = ss.accept(); // 如果没有客户端连接就会阻塞
                // 得到socket关联的对象输入流
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                // 得到socket关联的对象输出流
                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());

                Object obj = ois.readObject(); // 读取客户端发送的对象
                Message message = new Message();

                // 检查接收到的对象是否是User类型（用于登录）
                if (obj instanceof User) {
                    User user = (User) obj;
                    // 验证用户
                    if (checkUser(user.getUserId(), user.getUserPwd())) { // 登入成功
                        message.setMesType(MessageType.MESSAGE_LOGIN_SUCCEED);
                        oos.writeObject(message);

                        // 创建一个线程，和客户端保持通信，该线程持有socket对象
                        ServerConnectClientThread serverConnectClientThread =
                                new ServerConnectClientThread(socket, user.getUserId());
                        // 启动该线程
                        serverConnectClientThread.start();
                        // 把线程对象放入集合中，进行管理
                        ManageClientThread.addClientThread(user.getUserId(), serverConnectClientThread);

                        // 登录成功后发送离线消息
                        ServerConnectClientThread.sendOfflineMessages(user.getUserId());

                    } else {
                        System.out.println("用户 id = " + user.getUserId() +
                                ",pwd = " + user.getUserPwd() + " 验证失败");
                        message.setMesType(MessageType.MESSAGE_LOGIN_FAIL);
                        oos.writeObject(message);
                        socket.close(); // 关闭socket
                    }

                    // 检查接收到的对象是否是Message类型（用于注册）
                } else if (obj instanceof Message) {
                    message = (Message) obj;
                    if (message.getMesType().equals(MessageType.MESSAGE_REGISTER)) {
                        User newUser = message.getUser();

                        // 检查用户是否已存在
                        if (!isUserExists(newUser.getUserId())) {
                            // 注册成功，保存用户
                            addUser(newUser);
                            message.setMesType(MessageType.MESSAGE_REGISTER_SUCCEED);
                        } else {
                            message.setMesType(MessageType.MESSAGE_REGISTER_FAIL);
                        }

                        // 将注册结果返回给客户端
                        oos.writeObject(message);
                        socket.close(); // 关闭socket
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 如果服务端退出while,说明服务器不在监听，因此关闭ServerSocket
            try {
                ss.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
